#ifndef OA_CORE_EVENTHANDLERQUEUE_H
#define OA_CORE_EVENTHANDLERQUEUE_H

#include "libs.h"
#include "util.h"
#include "core/eventbridge.h"

namespace core {
	class EventChannel;

	template <typename tEvent>
	class _OA_export EventHandlerQueue {
	private: //the entire class is private, so no object may use it
		friend class EventChannel; //except for the EventChannel

		typedef EventHandler<tEvent> EventHandlerType;
		typedef boost::shared_ptr<EventHandlerType> EventHandlerPtr;
		typedef std::list<EventHandlerPtr> HandlerList;
		typedef typename HandlerList::iterator HandlerIterator;
		typedef typename HandlerList::const_iterator ConstHandlerIterator;
		typedef boost::mutex Mutex;
		typedef boost::mutex::scoped_lock ScopedLock;

		HandlerList mHandlerList;
		Mutex mMutex;

		static EventHandlerQueue& instance() {
			static EventHandlerQueue anInstance;
			return anInstance;
		}

		template <class tHandler>
		void add(tHandler& handler) {
			ScopedLock lock(mMutex);

			mHandlerList.push_back(
				EventHandlerPtr(new EventBridge<tEvent, tHandler>(handler))
			);
		}

		void broadcast(const tEvent& object) {
			ScopedLock lock(mMutex);

			ConstHandlerIterator next;
			for (ConstHandlerIterator it = mHandlerList.begin(); it != mHandlerList.end(); ) {
				next = it++; 
				(*next)->handle(object);
			}
		}

		template <class tHandler>
		class PointsToSame {
		public:
			typedef EventBridge<tEvent, tHandler> BridgeType;

			const tHandler& mHandler;

			PointsToSame(const tHandler& h): mHandler(h) {}

			bool operator()(EventHandlerPtr ptr) {
				return ((*boost::static_pointer_cast<BridgeType>(ptr)) == mHandler);
			}
		};

		template <class tHandler>
		void remove(const tHandler& handler) {
			ScopedLock lock(mMutex);

			PointsToSame<tHandler> pts(handler);
			mHandlerList.remove_if(pts);
		}
	};
}

#endif
